﻿using YoloDotNet;
using YoloDotNet.Enums;
using YoloDotNet.Models;
using YoloDotNet.Extensions;
using SkiaSharp;
using System.Diagnostics;

namespace YoloImageDetect
{

    public partial class ImageForm : Form
    {


        private MainForm mainForm;
        YoloOnnxRuntimeDetector yoloDetector = null;
     
        public ImageForm(MainForm form)
        {
            InitializeComponent();
            mainForm = form;

            yoloDetector = YoloOnnxRuntimeDetector.InitDefaultInstance(true);
            string defaultModelPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AIYolo", CommonConsts.YOLO_DEFAULT_MODEL_X + CommonConsts.YOLO_SUFFIX);
            this.textBoxYoloModelPath.Text = defaultModelPath;
        }
        private static string picpath;

        private void buttonChooseImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            // 设置对话框属性
            openFileDialog.Title = "选择图片文件";
            openFileDialog.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*";
            openFileDialog.Multiselect = false; // 只能选择一个文件


            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                // 获取选择的文件路径
                string selectedFilePath = openFileDialog.FileName;
                pictureBox1.Image = Image.FromFile(selectedFilePath);
                picpath = selectedFilePath;
                this.labelImagePath.Text = @$"图片: {selectedFilePath}";
                this.pictureBox2.Image = null;
            }
        }

        private void buttonConfirm_Click(object sender, EventArgs e)
        {

            label2.Text = "";

            if (string.IsNullOrEmpty(picpath))
            {
                MessageBox.Show("请先选择图片！");
                return;
            }
            detect();
        }
        private void detect()
        {
            float confThreshold = ((float)Convert.ToDouble(this.numericUpDownConfThreshold.Value));
            try
            {
                // 加载图片并运行 YOLO 检测
                Image image = new System.Drawing.Bitmap(picpath);
                byte[] imgaeBytes = null;
                using (var stream = new MemoryStream())
                {
                    image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    imgaeBytes = stream.ToArray();
                }
                string requestResult = yoloDetector.Detect(imgaeBytes, confThreshold);
 
                dynamic rejsonobj = Newtonsoft.Json.JsonConvert.DeserializeObject<DetectionResult>(requestResult);
                List<Prediction> predictions = rejsonobj.results;

                Image drawedImage = YoloOnnxRuntimeDetector.DrawImagePredictions(picpath, predictions, yoloDetector.GetClassNames());
                pictureBox2.Image = drawedImage;

            }
            catch (Exception ex)
            {
                MessageBox.Show($"检测失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void buttonSave_Click(object sender, EventArgs e)
        {
            if (pictureBox2.Image == null)
            {
                MessageBox.Show("没有可保存的图像！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            try
            {
                string timestamp = DateTime.Now.ToString("HHmmss_fff");
                string savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "res", $@"new_image_{timestamp}.jpg"); 
    
                // 确保目录存在
                Directory.CreateDirectory(Path.GetDirectoryName(savePath));
                // 将图像转换为 Bitmap
                using (Bitmap bitmap = new Bitmap(pictureBox2.Image))
                {
                    bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                label2.Text = "保存成功！";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void ImageForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            picpath = "";
            mainForm = null;
        }

        private void buttonOpenFileDir_Click(object sender, EventArgs e)
        {
            string directoryPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "res"); 

            // 检查目录是否存在
            if (Directory.Exists(directoryPath))
            {
                // 打开目录（使用系统默认的文件资源管理器）
                Process.Start(new ProcessStartInfo(directoryPath)
                {
                    UseShellExecute = true, // 必须设为 true 才能打开目录
                    Verb = "open" // 动作：打开目录
                });
            }
            else
            {
                // 目录不存在
                MessageBox.Show($"目录不存在：{directoryPath}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void buttonChooseOnnxModel_Click(object sender, EventArgs e)
        {
            string srcModelPath = DialogHelper.SelectFilePath(DialogHelper.FILTER_MODEL_ONNX);
            if (string.IsNullOrEmpty(srcModelPath))
            {
                MessageBox.Show("未选择任何模型文件");
                return;
            }
            string srcYamlPath = DialogHelper.SelectFilePath(DialogHelper.FILTER_MODEL_YAML);
            if (string.IsNullOrEmpty(srcYamlPath))
            {
                MessageBox.Show("未选择任何模型标签配置文件");
                return;
            }
            // 获取当前项目的根目录路径
            string rootDirectory = AppDomain.CurrentDomain.BaseDirectory;
            // 定义相对路径
            string relativePath = Path.Combine(rootDirectory, "AIYolo");
            if(!Directory.Exists(relativePath))
            {
                Directory.CreateDirectory(relativePath);
            }
            string modelCode = CommonConsts.YOLO_DEFAULT_MODEL_X;
            string destModelPath = Path.Combine(relativePath, modelCode + CommonConsts.YOLO_SUFFIX);
            string dateTimeStr = DateTime.Now.ToString("yyyyMMddHHmmss");
            if (File.Exists(destModelPath))
            {
                if (DialogResult.Yes == MessageBox.Show("是否覆盖原模型文件", "提示", MessageBoxButtons.YesNo))
                {
                    File.SetAttributes(destModelPath, FileAttributes.Normal);
                    // 备份
                    File.Copy(destModelPath, destModelPath + "_bak" + dateTimeStr, true);
                }
                else
                {
                    return;
                }
            }
            File.Copy(srcModelPath, destModelPath, true);
            string destYamlPath = Path.Combine(relativePath, modelCode + CommonConsts.YOLO_YAML_SUFFIX);
            if (File.Exists(destYamlPath))
            {
                File.SetAttributes(destYamlPath, FileAttributes.Normal);
                // 备份
                File.Copy(destYamlPath, destYamlPath + "_bak" + dateTimeStr, true);
            }
            File.Copy(srcYamlPath, destYamlPath, true);


            yoloDetector = YoloOnnxRuntimeDetector.InitDefaultInstance(true);
            this.textBoxYoloModelPath.Text = destModelPath;
        }
    }
}
